using System;
using System.Text;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;


namespace researcher
{

  /// <summary>
  /// Summary description for ResearchManager
  /// </summary>
  public class ResearchManager
  {
    private Stock stockSymbol;
    private bool isValidFlag;
    private List<string> urlQueue;
    private List<ResearchAssistant> assistants;
    private int threadThreshhold;


    public ResearchManager()
    {
      this.isValidFlag = false;
      this.threadThreshhold = 4;
    }


    private void FetchLinks()
    {
      if (stockSymbol != null)
      {
        string searchUrl = "http://finance.yahoo.com/q?s=" + (this.stockSymbol.CompanyName) + "&x=0&y=0";
//        Console.WriteLine("Search URL: " + searchUrl);
        StringBuilder sb = new StringBuilder();
        byte[] buf = new byte[10240];

        try
        {
          HttpWebRequest request = (HttpWebRequest)WebRequest.Create(searchUrl);
          HttpWebResponse response = (HttpWebResponse)request.GetResponse();
          Stream resStream = response.GetResponseStream();

          string tempString = null;
          int count = 0;

          do
          {
            count = resStream.Read(buf, 0, buf.Length);
            if (count > 0)
            {
              tempString = Encoding.ASCII.GetString(buf, 0, count);
              sb.Append(tempString);
            }
          }
          while (count > 0);
        }
        catch (Exception e)
        {
          this.isValidFlag = false;
          throw;
        }

        if (sb.Length > 0)
        {
          urlQueue = this.ScrapeHtml(sb.ToString());
        }
      }
      else
      {
        this.isValidFlag = false;
      }
    }


    public void Research(Stock stock)
    {
      int idx;
      this.stockSymbol = stock;
      this.isValidFlag = true;
      this.FetchLinks();

      if (this.urlQueue != null && this.urlQueue.Count > 0)
      {
        int m = Math.Min(this.threadThreshhold, this.urlQueue.Count);
        this.assistants = new List<ResearchAssistant>();

        for (idx = 0; idx < urlQueue.Count; idx++)
        {
          ResearchAssistant asst = new ResearchAssistant();
          asst.Url = this.urlQueue[idx];
          asst.Manager = this;
          this.assistants.Add(asst);
        }

        for (idx = 0; idx < m; idx++) this.ResearchUrlsInQueue();
      }
    }


    public void ResearchUrlsInQueue()
    {
      lock (this)
      {
        int idx, count = 0;
        for (idx = 0; idx < this.urlQueue.Count; idx++)
        {
          if (assistants[idx].IsResearchInProgress || assistants[idx].IsResearchComplete)
          {
            count++;
          }
          else if (count < this.threadThreshhold)
          {
            ThreadStart asst = new ThreadStart(assistants[idx].ResearchUrl);
            Thread thread = new Thread(asst);
            thread.Start();
          }
          else
          {
            break;
          }
        }
      }
    }


    public void ThreadCompleteNotification()
    {
      ResearchUrlsInQueue();
    }


    private List<string> ScrapeHtml(string str)
    {
      Console.WriteLine(str);
      if (this.IsValid)
      {
        List<string> list = new List<string>();

        if (str != null)
        {
          for (Match match = Regex.Match(str, @"<td class=""[^""]+"" rowspan=""2"">&#149;</td><td><a href=""([^""]+)"">"); match.Success; match = match.NextMatch())
          {
            GroupCollection gc = match.Groups;
            list.Add(gc[1].Value);
          }
        }

        if (list.Count == 0)
        {
          list = null;
        }

        return list;
      }
      else
      {
        throw new Exception();
      }
    }


    public Stock StockSymbol
    {
      get { return stockSymbol; }
      set { stockSymbol = value; }
    }


    public List<string> UrlQueue
    {
      get { return urlQueue; }
      set { urlQueue = value; }
    }


    public bool IsValid
    {
      get { return isValidFlag; }
      set { isValidFlag = value; }
    }
  }
}
